/*
 * @ (#) Packet.java Jun 5, 2008
 *
 * 
 */
package com.aspire.nm.component.cmppserver.filter.coder.packet;

import java.nio.ByteBuffer;

/**
 * 用于存放与协议相关的一个完整封包
 * 
 * <p>
 * JNSF并不强制要求使用此类, 但某些情况下使用此类可以减少很多工作。<br />
 * 
 * Packet底层有一个ByteBuffer来存放从网络读到字节序列, 或者经过编码后即将发送到网络的字节序列,
 * 
 * 当向网络发送封包时, ByteBuffer的数据由具体实现类的对象内部直接填充或者在编码器中填充, 也就是说底层数据由具体实现类的对象或具体编码器实现类的对象提供.
 * 
 * 当从网络读时, ByteBuffer由解码器负责填充, 也就是说底层数据由具体的解码器实现提供.<br />
 * 
 * 基于ByteBuffer请参见java.nio.ByteBuffer<br />
 * </p>
 * 
 * @author	zhangkai
 * @version 2.0.0
 * @since 2.0.0
 * 
 * LAST MODIFIED: 2008-12-29
 */
public class Packet{
	
	private ByteBuffer buffer;
	
	/**
	 * 构造Packet对象
	 */
	public Packet(){}
	
	/**
	 * 用指定的字节数组构造Packet对象
	 * @param bytes	代表封包数据的字节数组
	 */
	public Packet(byte[] bytes){
		this.buffer = ByteBuffer.wrap(bytes);
	}
	
	/**
	 * 用指定的ByteBuffer构造Packet对象
	 * @param buffer ByteBuffer
	 */
	public Packet(ByteBuffer buffer){
		this.buffer = buffer;
	}
	
	/**
	 * 返回底层字节数组
	 * @return 底层字节数组
	 */
	public byte[] getBytes(){
		return buffer.array();
	}
	
	/**
	 * 获得底层用于存放数据的ByteBuffer, 返回的ByteBuffer是只读的
	 * @return 底层ByteBuffer的只读副本
	 */
	public ByteBuffer getByteBuffer(){
		return buffer.asReadOnlyBuffer();
	}
	
	// -- PROTECTED METHOD ----------------------------------------------------
	
	/**
	 * 为Packet申请底层存储空间。之前已存在的数据将被清除。
	 * @param capacity 存储空间大小
	 */
	protected ByteBuffer allocate(int capacity){
		return buffer = ByteBuffer.allocate(capacity);
	}
	
	/**
	 * 填充底层ByteBuffer, 之前已有数据将被清除
	 * @param bytes 字节数组
	 */
	protected void setBytes(byte[] bytes){
		this.buffer = ByteBuffer.wrap(bytes);
	}
	
	/**
	 * 填充底层ByteBuffer, 之前已有数据将被清除, 并且通过参数ByteBuffer的其他引用对对象的更改将影响底层数据。
	 * @param bytes ByteBuffer
	 */
	protected void setByteBuffer(ByteBuffer bytes){
		this.buffer = bytes;
	}
	
	/**
	 * 写入byte
	 * @param b byte
	 * @return ByteBuffer
	 */
	protected ByteBuffer put(byte b){
		return buffer.put(b);
	}
	
	/**
	 * 写入byte[]
	 * @param src byte[]
	 * @return ByteBuffer
	 */
	protected ByteBuffer put(byte[] src){
		return buffer.put(src);
	}
	
	/**
	 * 写入byte[]
	 * @param src byte[]
	 * @param offset byte[]的起始位置
	 * @param length 写入长度
	 * @return ByteBuffer
	 */
	protected ByteBuffer put(byte[] src, int offset, int length){
		return buffer.put(src, offset, length);
	}
	
	/**
	 * 写入ByteBuffer
	 * @param src ByteBuffer
	 * @return ByteBuffer
	 */
	protected ByteBuffer put(ByteBuffer src){
		return buffer.put(src);
	}
	
	/**
	 * 写入byte到ByteBuffer指定位置
	 * @param index ByteBuffer中指定位置
	 * @param b byte
	 * @return ByteBuffer
	 */
	protected ByteBuffer put(int index, byte b){
		return buffer.put(index, b);
	}
	
	/**
	 * 写入char
	 * @param value char
	 * @return ByteBuffer
	 */
	protected ByteBuffer putChar(char value){
		return buffer.putChar(value);
	}
	
	/**
	 * 写入char到ByteBuffer指定位置
	 * @param index ByteBuffer指定位置
	 * @param value char
	 * @return ByteBuffer
	 */
	protected ByteBuffer putChar(int index, char value){
		return buffer.putChar(index, value);
	}
	
	/**
	 * 写入double
	 * @param value double
	 * @return ByteBuffer
	 */
	protected ByteBuffer putDouble(double value){
		return buffer.putDouble(value);
	}
	
	/**
	 * 写入double到ByteBuffer指定位置
	 * @param index ByteBuffer指定位置
	 * @param value double
	 * @return ByteBuffer
	 */
	protected ByteBuffer putDouble(int index, double value){
		return buffer.putDouble(index, value);
	}
	
	/**
	 * 写入float
	 * @param value float
	 * @return ByteBuffer
	 */
	protected ByteBuffer putFloat(float value){
		return buffer.putFloat(value);
	}
	
	/**
	 * 写入float到ByteBuffer指定位置
	 * @param index ByteBuffer指定位置
	 * @param value float
	 * @return ByteBuffer
	 */
	protected ByteBuffer putFloat(int index, float value){
		return buffer.putFloat(index, value);
	}
	
	/**
	 * 写入int
	 * @param value int
	 * @return ByteBuffer
	 */
	protected ByteBuffer putInt(int value){
		return buffer.putInt(value);
	}
	
	/**
	 * 写入int到ByteBuffer指定位置
	 * @param index ByteBuffer指定位置
	 * @param value int
	 * @return ByteBuffer
	 */
	protected ByteBuffer putInt(int index, int value){
		return buffer.putInt(index, value);
	}
	
	/**
	 * 写入long
	 * @param value long
	 * @return ByteBuffer
	 */
	protected ByteBuffer putLong(long value){
		return buffer.putLong(value);
	}
	
	/**
	 * 写入long到ByteBuffer指定位置
	 * @param index ByteBuffer指定位置
	 * @param value long
	 * @return ByteBuffer
	 */
	protected ByteBuffer putLong(int index, long value){
		return buffer.putLong(index, value);
	}
	
	/**
	 * 写入short
	 * @param value short
	 * @return ByteBuffer
	 */
	protected ByteBuffer putShort(short value){
		return buffer.putShort(value);
	}
	
	/**
	 * 写入short到ByteBuffer指定位置
	 * @param index ByteBuffer指定位置
	 * @param value short
	 * @return ByteBuffer
	 */
	protected ByteBuffer putShort(int index, short value){
		return buffer.putShort(index, value);
	}
	
	/**
	 * 写入指定字串
	 * @param value 字符串
	 * @return 底层缓冲区ByteBuffer
	 */
	protected ByteBuffer putString(String value){
		return buffer.put(value.getBytes());
	}
	
	/**
	 * 写入指定字串
	 * 
	 * @param value 准备写入的字串
	 * @param beginIndex 字串起始字符位置
	 * @param endIndex	字串终止字符位置
	 * @return 底层缓冲区ByteBuffer
	 */
	protected ByteBuffer putString(String value, int beginIndex, int endIndex){
		return buffer.put((value.substring(beginIndex, endIndex)).getBytes());
	}
	
	/**
	 * 写入指定字串的特定长度到缓冲区, 如果字串为null或者字串长度不足, 则左补\0
	 * @param value 字符串
	 * @param len 写入长度
	 * @return 底层缓冲区ByteBuffer
	 */
	protected ByteBuffer putStringLeftPad(String value, int len){
		if(len <= 0) return buffer;
		
		int add = value == null ? len : (len <= value.length() ? 0 : value.length() - len);
		
		if(add == 0)
			buffer.put(value.getBytes(), 0, len);
		else if(add == len){
			buffer.put(new byte[len]);
		}else{
			buffer.put(new byte[add]);
			buffer.put(value.getBytes());
		}
		
		return buffer;
	}
	
	/**
	 * 写入制定字串的特定长度到缓冲区, 如果字串为null或者字串长度不足, 则右补\0
	 * @param value 字符串
	 * @param len 写入长度
	 * @return 底层缓冲区ByteBuffer
	 */
	protected ByteBuffer putStringRightPad(String value, int len){
		if(len <= 0) return buffer;
		
		int add = value == null ? len : (len <= value.length() ? 0 : len - value.length());
		
		if(add == 0)
			buffer.put(value.getBytes(), 0, len);
		else if(add == len){
			buffer.put(new byte[len]);
		}else{
			buffer.put(value.getBytes());
			buffer.put(new byte[add]);
		}
		
		return buffer;
	}
	
	/**
	 * 取得一个byte(相对)
	 * @return byte
	 */
	protected byte get(){
		return buffer.get();
	}
	
	/**
	 * 取得byte[]
	 * @param desc 目的byte[]
	 * @return 底层ByteBuffer
	 */
	protected ByteBuffer get(byte[] desc){
		return buffer.get(desc);
	}
	
	/**
	 * 取得byte[]
	 * @param dst 目的byte[]
	 * @param offset dst起始位置
	 * @param length 读取长度
	 * @return 底层ByteBuffer
	 */
	protected ByteBuffer get(byte[] dst, int offset, int length){
		return buffer.get(dst, offset, length);
	}
	
	/**
	 * 取得byte(绝对)
	 * @param index ByteBuffer绝对位置
	 * @return int
	 */
	protected byte get(int index){
		return buffer.get(index);
	}
	
	/**
	 * 取得char(相对)
	 * @return char
	 */
	protected char getChar(){
		return buffer.getChar();
	}
	
	/**
	 * 取得char(绝对)
	 * @param index ByteBuffer绝对位置
	 * @return char
	 */
	protected char getChar(int index){
		return buffer.getChar(index);
	}
	
	/**
	 * 取得double(相对)
	 * @return double
	 */
	protected double getDouble(){
		return buffer.getDouble();
	}
	
	/**
	 * 取得double(绝对)
	 * @param index ByteBuffer绝对位置
	 * @return double
	 */
	protected double getDouble(int index){
		return buffer.getDouble(index);
	}
	
	/**
	 * 取得float(相对)
	 * @return float
	 */
	protected float getFloat(){
		return buffer.getFloat();
	}
	
	/**
	 * 取得float(绝对)
	 * @param index ByteBuffer绝对位置
	 * @return float
	 */
	protected float getFloat(int index){
		return buffer.getFloat(index);
	}
	
	/**
	 * 取得int(相对)
	 * @return int
	 */
	protected int getInt(){
		return buffer.getInt();
	}
	
	/**
	 * 取得int(绝对)
	 * @param index ByteBuffer绝对位置
	 * @return int
	 */
	protected int getInt(int index){
		return buffer.getInt(index);
	}
	
	/**
	 * 取得long(相对)
	 * @return long
	 */
	protected long getLong(){
		return buffer.getLong();
	}
	
	/**
	 * 取得long(绝对)
	 * @param index ByteBuffer绝对位置
	 * @return long
	 */
	protected long getLong(int index){
		return buffer.getLong(index);
	}
	
	/**
	 * 取得short(相对)
	 * @return short
	 */
	protected short getShort(){
		return buffer.getShort();
	}
	
	/**
	 * 取得short(绝对)
	 * @param index ByteBuffer绝对位置
	 * @return short
	 */
	protected short getShort(int index){
		return buffer.getShort(index);
	}
	
	/**
	 * 取得指定长度的字符串
	 * @param length 长度
	 * @return 字符串
	 */
	protected String getString(int length){
		byte[] bytes = new byte[length];
		buffer.get(bytes);
		String tmp = new String(bytes);
		int index = tmp.indexOf(0);
		if(index != -1)
			tmp = tmp.substring(0, index);
		return tmp;
	}
}
